home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
v8n07.arc
/
LASERLST.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-03-13
|
35KB
|
957 lines
PAGE 75,132
TITLE "LASERLST - List file to HP LaserJet"
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
ORG 100H
START: JMP MAIN ; go to start of program
HEADER_MSG DB "LaserLst 1.0 (c) 1989 Ziff Communications Co.", 0DH,0AH
DB "PC Magazine",254," Michael Holmes & Bob Flanders",0DH,0AH
CRLF DB 0DH,0AH
DOLLAR DB "$"
; ---------------------------------------------------------------------------
; Initialized work areas
; ---------------------------------------------------------------------------
ARG1 DW 0 ; addr of first argument
ARG2 DW 0 ; addr of second argument
PHANDLE DW 4 ; printer handle (stdprn)
TABCOL DW 8 ; tab width
NEWPAGE DB 0 ; new page requested flag
HPSTATE DB 0 ; printer state (1 = initialized)
TITLE_ DB 1BH,"&dD" ; title line for heading
TITLE_DTE DB "mm/dd/yyyy " ; ..and display
TITLE_TME DB "hh:mm Filename: "
TITLE_FLE DB 19 dup(32)
TITLE_DSP EQU $-TITLE_DTE
DB " Page"
TITLE_PGE DB "xxxx",0dh,0ah,0ah
DB 1BH,"&d@"
TITLE_LEN EQU $-TITLE_ ; length of title
;----------------------------------------------------------------------
; DTA structure for DOS "find matching" call
;----------------------------------------------------------------------
DTA EQU 80H ; dta offset
DTA_ATTR EQU BYTE PTR DTA+21 ; file attribute
DTA_TIME EQU WORD PTR DTA_ATTR+1 ; file time
DTA_DATE EQU WORD PTR DTA_TIME+2 ; file date
DTA_LSIZ EQU WORD PTR DTA_DATE+2 ; file lsw of size
DTA_HSIZ EQU WORD PTR DTA_LSIZ+2 ; file msw of size
DTA_NAME EQU BYTE PTR DTA_HSIZ+2 ; file name of file
DTA_LEN EQU DTA_NAME+15-DTA ; length of dta find entry
;----------------------------------------------------------------------
; Messages to user
;----------------------------------------------------------------------
FILENF DB "File not found.",0DH,0AH,"$"
PRTOERR DB "Could not open output file.",0DH,0AH,"$"
FORMAT DB 0DH,0AH,"SYNTAX:",09H,"LASERLST [d:][path]filename[.ext] "
DB "[outfile] [/Tn]",0DH, 0AH, 0AH
DB " ofile defaults to LPT1:",0DH,0AH
DB " n is tab width (16 max)",0DH,0AH,"$"
;----------------------------------------------------------------------
; HP control strings
;----------------------------------------------------------------------
STRING1 DB 1BH,"E",1BH,"&l1O",1BH,"(s17H",1BH,"&l5.14C"
DB 1BH,"&l71F",1BH,"&l6E",1BH,"(s-3B"
DB 1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
STRING1_LEN EQU $-STRING1
STRING2 DB 0ch,1BH,"E"
STRING2_LEN EQU $-STRING2
STRING3 DB 1BH,"&a0R",1BH,"&a90M",1BH,"&a88L",0DH,0AH,0DH,0AH
STRING3_LEN EQU $-STRING3
STRING4 DB "|", 0DH,0AH
STRING5 DB 1BH,"&a0R",1BH,"&a171M",1BH,"&a91L",0DH
STRING5_LEN EQU $-STRING5
STRING6 DB 0CH,1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
STRING6_LEN EQU $-STRING6
; ---------------------------------------------------------------------------
; MAIN - Mainline of program
; ---------------------------------------------------------------------------
MAIN PROC ; start of program
CALL INIT ; initialize program
MAIN10: CALL OPEN ; open the input file
JC MAIN80 ; if we can't .. try next
MAIN20: CALL READ ; read a block
CALL PRINT ; print the line
OR SI, SI ; q. end of file?
JNZ MAIN20 ; a. no .. get next line
MOV BX, FHANDLE ; bx = input file handle
MOV AH, 3EH ; ah = close file
INT 21H ; .. ask DOS to do it
MAIN80: MOV AH, 4FH ; ah = find next file
INT 21H ; q. file found?
JNC MAIN10 ; a. yes .. continue
MOV DX, OFFSET DOLLAR ; dx -> null message
CALL DIE ; .. say goodnight
MAIN ENDP
; ---------------------------------------------------------------------------
; INIT - Handle initialization
; ---------------------------------------------------------------------------
INIT PROC
CLD ; assure ascending
MOV AH, 19H ; ah = get current drive
INT 21H ; al = current drive
MOV EDRV, AL ; save entry drive
MOV SI, OFFSET EDIR ; si -> current directory area
MOV BYTE PTR [SI], '\' ; .. start with backslash
INC SI ; si -> next byte
XOR DL, DL ; dl = default drive
MOV AH, 47H ; ah = get current dir
INT 21H ; .. save in area
MOV DX, OFFSET HEADER_MSG ; dx -> header message
MOV AH, 9 ; ah = print ascii$ message
INT 21H ; .. ask DOS to do it
CALL PARMS ; check parameters
CMP ARG2, 0 ; q. arg2 specified?
JE INIT20 ; a. yes .. skip open
MOV DX, ARG2 ; dx -> arg2 value
MOV AH, 3CH ; ah = create file
XOR CX, CX ; .. cx = file attributes
INT 21H ; q. open the file ok?
JNC INIT10 ; a. yes .. continue
MOV DX, OFFSET PRTOERR ; dx -> open error message
CALL DIE ; .. you're dead, Jim.
INIT10: MOV PHANDLE, AX ; save printer handle
INIT20: CALL DFLPATH ; set up dir & drive
MOV AH, 4EH ; ah = find first
MOV DX, OFFSET FILENAME ; dx -> file to find
XOR CX, CX ; cx = search attribute
INT 21H ; q. find first file ok?
JNC INIT90 ; a. yes .. continue
MOV DX, OFFSET FILENF ; dx -> file not found
CALL DIE ; .. gasp you're final breath
INIT90: RET ; return to caller
INIT ENDP
; ---------------------------------------------------------------------------
; OPEN - Opens the next file to process and update title line
; Exit: Carry indicates file would not open.
; ---------------------------------------------------------------------------
OPEN PROC
MOV DX, OFFSET DTA_NAME ; dx -> file name
MOV AX, 3D00H ; al = open for read
INT 21H ; .. ask DOS to do it.
JNC OPEN05 ; ok .. continue
RET ; else .. return if error
OPEN05: MOV FHANDLE, AX ; save file handle
MOV LASTBUFF, 0 ; show last buffer not read
MOV SI, OFFSET DTA_NAME ; si -> file name
MOV DI, OFFSET TITLE_FLE ; di -> file name area
PUSH DI ; .. save it
MOV AL, ' ' ; al = blank
MOV CX, 15 ; .. amount to blank
REP STOSB ; .. clear the file name
POP DI ; .. restore output pointer
OPEN10: LODSB ; al = byte from file name
OR AL, AL ; q. end of name?
JZ OPEN20 ; a. yes .. end loop
STOSB ; store a byte
JMP OPEN10 ; .. and move next
OPEN20: MOV BL, '0' ; fill value
MOV AX, DS:DTA_DATE ; ax = date field
PUSH AX ; save for later
PUSH AX ; .. again
MOV CL, 5 ; cl = shift value
SHR AX, CL ; .. mm to lower bits
AND AX, 0FH ; .. upper bits off
MOV CX, 2 ; cx = number of characters
MOV DI, OFFSET TITLE_DTE ; di -> mm
CALL ITOA ; .. move in mm
POP AX ; ax = date
AND AX, 1FH ; al = dd
MOV CX, 2 ; cx = number of chars
MOV DI, OFFSET TITLE_DTE+3 ; di -> dd
CALL ITOA ; .. move into dd
POP AX ; ax = date
MOV CL, 9 ; cl = shift amount
SHR AX, CL ; .. ax = yy
ADD AX, 1980 ; ax = year
MOV CX, 4 ; cx = length of output
MOV DI, OFFSET TITLE_DTE+6 ; di -> yyyy
CALL ITOA ; .. move into yyyy
MOV AX, DS:DTA_TIME ; ax = time
PUSH AX ; .. save for later
MOV CL, 11 ; cl = shift value
SHR AX, CL ; .. ax = hh
MOV CX, 2 ; cx = length of output
MOV DI, OFFSET TITLE_TME ; di -> hh
CALL ITOA ; .. move into hh
POP AX ; ax = time
MOV CL, 5 ; cl = shift value
SHR AX, CL ; ax = mm
AND AX, 3FH ; .. upper bits off
MOV CX, 2 ; cx = length of output
MOV DI, OFFSET TITLE_TME+3 ; di -> mm
CALL ITOA ; .. move into mm
MOV AH, 40H ; ah = write to device
MOV BX, 1 ; bx = stdout device
MOV CX, TITLE_DSP ; cx = length to display
MOV DX, OFFSET TITLE_DTE ; dx -> part of header line
INT 21H ; issue dos call
MOV AH, 40H ; ah = write to device
MOV BX, 1 ; bx = stdout device
MOV CX, 2 ; cx = length to display
MOV DX, OFFSET CRLF ; dx -> <cr><lf> string
INT 21H ; issue dos call
CLC ; show all went ok
OPEN90: RET
OPEN ENDP
; ---------------------------------------------------------------------------
; READ - Read the next buffer full
; Exit: si -> next line, 0 if eof, cx = length of line
; ---------------------------------------------------------------------------
READ PROC
PUSH AX ; save registers
PUSH BX
PUSH DX
MOV SI, 0 ; si -> nothing
CMP LASTBUFF, 1 ; q. last buffer have 1ah?
JE READ90 ; a. yes .. end it all
MOV AH, 03FH ; ah = read file
MOV BX, FHANDLE ; bx = handle of file to read
MOV CX, BUFLEN ; cx = amount to read
MOV DX, OFFSET BUFFER ; dx -> buffer
INT 21H ; read, please
JC READ90 ; error .. return eof
OR AX, AX ; q. any read?
JZ READ90 ; a. yes .. return with something
MOV SI, OFFSET BUFFER ; si -> start of line
MOV CX, AX ; cx = nbr of characters read
MOV BX, AX ; .. and bx
MOV DI, SI ; di -> chars read
MOV AL, 1AH ; al = EOF indicator
REPNE SCASB ; q. eof found?
JNE READ80 ; a. no .. continue
INC CX ; .. increment count
NEG CX ; .. and negate it
MOV LASTBUFF, 1 ; .. and set lastbuff flag
READ80: ADD CX, BX ; q. any bytes this buffer?
JNZ READ90 ; a. yes .. continue
MOV SI, 0 ; a. else .. show end of file.
READ90: POP DX ; restore registers
POP BX ;
POP AX ;
RET ; ..and return to caller
READ ENDP
; ---------------------------------------------------------------------------
; PRINT - Print requested data
; Entry: si -> string to print or 0, cx = length of input string
; ---------------------------------------------------------------------------
PRINT PROC
OR SI, SI ; q. end of file call?
JNE PRINT10 ; a. no .. continue
CALL EPILOGUE ; put out trailing characters
RET ; ..and return to caller
PRINT10: PUSH AX ; save registers
PUSH BX
PUSH CX
PUSH DX
PUSH SI
CMP HPSTATE, 0 ; q. initial state?
JNE PRINT20 ; a. no .. continue
CALL PROLOGUE ; send out initial string
PRINT20: CALL EXPAND ; handle tab expansion
MOV DX, SI ; dx -> start of new buffer
MOV BX, CX ; bx = nbr of chars in buffer
XOR CX, CX ; cx = nbr of chars to print
MOV AH, USEDLEN ; ah = printed chars in this line
PRINT30: LODSB ; al = first character
CMP AL, 0CH ; q. formfeed?
JNE PRINT40 ; a. yes .. process it
CALL LINEPRT ; print the line
CALL PAGEBREAK ; do a page break
XOR AH, AH ; ah = nbr of columns used
DEC BX ; bx = decrement remaining count
INC DX ; dx -> next printable character
JMP PRINT70 ; ..and continue w/common code
PRINT40: CMP AL, 0AH ; q. linefeed?
JNE PRINT50 ; a. no .. continue
DEC BX ; bx = remaining chars in buffer
INC CX ; cx = nbr of characters to print
CALL LINEPRT ; print the line
XOR AH, AH ; ah = nbr of columns used
CALL BUMPLINE ; increment/test line counter
JMP PRINT70 ; ..and continue w/common code
PRINT50: CMP AL, 0DH ; q. carriage return?
JNE PRINT55 ; a. no .. continue
JMP SHORT PRINT57 ; ..and continue w/common code
PRINT55: CMP AL, 08H ; q. BackSpace?
JNE PRINT60 ; a. no .. continue
DEC AH ; move back a column
JNS PRINT65 ; .. but not beyond first
PRINT57: XOR AH, AH ; ah = start of line
JMP SHORT PRINT65 ; .. and continue
PRINT60: INC AH ; increment nbr of columns used
PRINT65: INC CX ; ..and nbr of chars to print
DEC BX ; decrement remaining char count
CMP AH, 81 ; q. reached end of line?
JL PRINT70 ; a. no .. continue
CALL LINEPRT ; print upto page width
PUSH CX ; save registers
PUSH DX ;
MOV DX, OFFSET CRLF ; dx -> <cr><lf>
MOV CX, 2 ; cx = string length
CALL WRITE ; print the crlf to do line wrapping
POP DX ; restore registers
POP CX ;
XOR AH, AH ; ah = nbr of columns used
CALL BUMPLINE ; increment/test line counter
PRINT70: OR BX, BX ; q. anything left to check?
JNZ PRINT30 ; a. yes .. loop till done
CALL LINEPRT ; print the line
MOV USEDLEN, AH ; save nbr of columns used
POP SI ; restore registers
POP DX ;
POP CX ;
POP BX ;
POP AX ;
RET ; ..and return to caller
PRINT ENDP
; ---------------------------------------------------------------------------
; DIE - Display an error message and return to DOS
; Entry: dx -> error message ended in dollar sign.
; ---------------------------------------------------------------------------
DIE PROC
MOV AH, 9 ; ah = print string
INT 21H ; .. call dos to print error
MOV DL, EDRV ; dl = drive to select
MOV AH, 0EH ; ah = select drive
INT 21H ; .. select the drive
MOV DX, OFFSET EDIR ; dx -> directory
MOV AH, 3BH ; ah = CHDIR request
INT 21H ; .. ask DOS to do it
MOV AX, 4C00H ; ax = exit
INT 21H ; .. terminate routine
DIE ENDP
; ---------------------------------------------------------------------------
; PARMS - Parses the command line
; ---------------------------------------------------------------------------
PARMS PROC
CALL UPCASE ; upper case the parm area
MOV SI, 81H ; si -> parms area
PARMS10: LODSB ; get parameter character
CMP AL, '/' ; q. option?
JE PARMS80 ; a. yes .. check option
CMP AL, 0DH ; q. end of line?
JE PARMS50 ; a. yes .. exit
CMP AL, ' ' ; q. blank?
JNA PARMS10 ; a. yes .. skip
CALL ARG ; set the argument
JC PARMSERR ; .. die on an error
PARMS30: LODSB ; get next character
CMP AL, 0DH ; q. end of line?
JE PARMS50 ; a. yes .. process
CMP AL, '/' ; q. start of option?
JE PARMS80 ; a. yes .. process
CMP AL, ' ' ; q. end of PARMS?
JA PARMS30 ; a. no .. next char
CALL ENDPARM ; terminate parm string
JMP PARMS10 ; .. look for next
PARMS50: CALL ENDPARM ; terminate parm string
CMP ARG1, 0 ; q. PARMS 1 available?
JE PARMSERR ; a. no .. error
RET ; .. else .. return to caller
PARMS80: CALL ENDPARM ; terminate parm string
LODSB ; al = option character
CMP AL, 'T' ; q. Tab width?
JNE PARMSERR ; a. no .. error in option
CALL ATOI ; ax = tab width
CMP AX, 16 ; q. request greater than max?
JG PARMS10 ; a. yes .. unreasonable
MOV TABCOL, AX ; .. save tab width
JMP PARMS10 ; .. continue scan
PARMSERR: MOV DX, OFFSET FORMAT ; dx -> format message
CALL DIE ; abort
PARMS ENDP
; ---------------------------------------------------------------------------
; ARG - Setup pointers to the command line arguments
; Entry: si -> second character in argument.
; Exit: ARG1 or ARG2 pointers filled in.
; Carry set if more than 2 arguments detected.
; ---------------------------------------------------------------------------
ARG PROC
LEA BX, [SI-1] ; bx -> argument
CMP ARG1, 0 ; q. arg1 filled in?
JNE ARG10 ; a. yes .. check 2
MOV ARG1, BX ; save arg1 pointer
JMP SHORT ARG90 ; .. exit ok!
ARG10: CMP ARG2, 0 ; q. arg2 filled in?
JE ARG20 ; a. no .. fill it in
STC ; else .. error
RET ; .. and return to caller
ARG20: MOV ARG2, BX ; save arg2 pointer
ARG90: CLC ; show no error
RET ; return to caller
ARG ENDP
; ---------------------------------------------------------------------------
; ENDPARM - Handle parameters which end in a colon
; Entry: si -> first character past end of parameter
; ---------------------------------------------------------------------------
ENDPARM PROC
CMP BYTE PTR [SI-2], ':' ; q. argument end in a colon?
JNE ENDPARM10 ; a. no .. continue
MOV BYTE PTR [SI-2], 0 ; ..it doesn't any more
RET ; ..and return
ENDPARM10: MOV BYTE PTR [SI-1], 0 ; end the parameter
RET ; ..and return
ENDPARM ENDP
; ---------------------------------------------------------------------------
; DFLPATH - Setup the default drive and path
; ---------------------------------------------------------------------------
DFLPATH PROC
MOV DI, ARG1 ; di -> first arg
DFLPATH10: CMP BYTE PTR [DI+1], ':' ; q. drive specified?
JNE DFLPATH20 ; a. no .. use current drive
MOV DL, [DI] ; dl = drive to use
SUB DL, 'A' ; get requested drive number
MOV AH, 0EH ; set requested drive
INT 21H ; .. via dos
ADD DI, 2 ; di -> next part
DFLPATH20: PUSH DI ; save pointer
MOV BX, DI ; bx -> start of area
XOR AL, AL ; al = search for null
MOV CX, 128 ; very max to search
CLD
REPNE SCASB ; find end of arg
LEA SI, [DI-1] ; si -> nul
MOV CX, 0 ; cx = # chars to move
CMP SI, BX ; q. any file name
JE DFLPATH80 ; a. no .. error
DFLPATH30: DEC SI ; si -> prev char
CMP BYTE PTR [SI], '\' ; q. dir?
JE DFLPATH35 ; a. yes .. end of file name.
INC CX ; cx = char count
CMP SI, BX ; q. done?
JE DFLPATH37 ; a. yes .. move file name
JMP DFLPATH30 ; .. continue
DFLPATH35: INC SI ; si -> start of file name
DFLPATH37: OR CX, CX ; q. file name spec'd?
JZ DFLPATH80 ; a. no .. error
CMP CX, 12 ; q. too long?
JA DFLPATH85 ; a. yes .. error
PUSH SI ; save start pointer
MOV DI, OFFSET FILENAME ; di -> file name
INC CX ; .. assure nul moves too
REP MOVSB ; .. move in the file name
POP SI ; restore start pointer
POP DI ; .. and dir pointer
CMP SI, BX ; q. at start of parm?
JE DFLPATH90 ; a. yes .. return
INC BX ; bx -> next char
CMP SI, BX ; q. root only given?
JE DFLPATH40 ; a. yes .. continue
DEC SI ; si -> last \
DFLPATH40: MOV BYTE PTR [SI], 0 ; make dir ASCIIZ
DFLPATH50: MOV DX, DI ; dx -> directory
MOV AH, 3BH ; ah = CHDIR opcode
INT 21H ; .. change directory
JNC DFLPATH90 ; if ok .. continue
JMP SHORT DFLPATH85 ; dx -> baddir request
DFLPATH80: MOV DX, OFFSET FORMAT ; dx -> no file specified
CALL DIE
DFLPATH85: MOV DX, OFFSET FILENF ; dx -> invalid filename spec'd
CALL DIE
DFLPATH90: RET ; return to caller
DFLPATH ENDP
; ---------------------------------------------------------------------------
; EXPAND - Handle tab expansion
; Entry:
; si -> line read from file ended by a linefeed
; cx = length of line
; Exit:
; si -> reformatted line in output buffer
; cx = new line length
; ---------------------------------------------------------------------------
EXPAND PROC
PUSH AX ; save registers
PUSH BX
PUSH DX
PUSH DI
MOV DI, OFFSET OBUFF ; di -> start of output buffer
EXPAND10: LODSB ; al = character from input line
CMP AL, 09H ; q. tab character?
JNE EXPAND30 ; a. no .. continue processing
MOV AX, CURCOL ; ax = current column
DEC AX ; ax = column offset
XOR DX, DX ; dx:ax = current column
MOV BX, TABCOL ; bx = nbr of columns per tab
IDIV BX ; dx = space within tab stop
SUB BX, DX ; bx = spaces left in tab stop
MOV AL, 20H ; al = space char to padding string
EXPAND20: STOSB ; put a blank in output buffer
INC CURCOL ; bump current column nbr
DEC BX ; q. done yet?
JNZ EXPAND20 ; a. no .. keep looping
JMP SHORT EXPAND50 ; a. yes .. get next character
EXPAND30: CMP AL, 0DH ; q. carriage return?
JE EXPAND33 ; a. yes .. reset column
CMP AL, 0CH ; q. form feed?
JNE EXPAND35 ; a. no .. continue processing
EXPAND33: MOV CURCOL, 0 ; setup for start of new line
JMP SHORT EXPAND40 ; .. continue
EXPAND35: CMP AL, 08H ; q. backspace?
JNE EXPAND40 ; a. no .. continue
STOSB ; save the BS
DEC CURCOL ; .. move back a space
JNZ EXPAND50 ; .. get next character
MOV CURCOL, 1 ; init current column
JMP SHORT EXPAND50 ; .. continue
EXPAND40: STOSB ; move character to output line
CMP AL, 0AH ; q. line feed?
JE EXPAND50 ; a. yes .. don't count it
INC CURCOL ; bump current column nbr
EXPAND50: LOOP EXPAND10 ; ..loop till input exhausted
MOV SI, OFFSET OBUFF ; si -> start of output buffer
MOV CX, DI ; di -> just past last char of output
SUB CX, SI ; cx = nbr of characters in output
POP DI ; restore registers
POP DX
POP BX
POP AX
RET ; ..and return to caller
EXPAND ENDP
; ---------------------------------------------------------------------------
; LINEPRT - Handle printing a line
; Entry:
; dx -> start of line
; cx = nbr of characters to print
; Exit:
; dx -> start of next line
; cx = 0
; ---------------------------------------------------------------------------
LINEPRT PROC
JCXZ LINEPRT90 ; if nothing to print.. return
CMP NEWPAGE, 1 ; q. need a new page?
JNE LINEPRT10 ; a. no .. continue
CALL PAGEBREAK ; else .. do a pagebreak
LINEPRT10: CALL WRITE ; write the line
ADD DX, CX ; dx -> start of next line
XOR CX, CX ; cx = nbr of characters to print
LINEPRT90: RET
LINEPRT ENDP
; ---------------------------------------------------------------------------
; MKTITLE - Make the title line be ready to print
; Exit:
; dx -> title line
; cx = title line length
; ---------------------------------------------------------------------------
MKTITLE PROC
PUSH AX ; save registers
PUSH BX
PUSH DI
MOV AX, PAGENO ; ax = page number
MOV CX, 4 ; cx = length of output
MOV BL, ' ' ; bl = fill char (blank)
MOV DI, OFFSET TITLE_PGE ; di -> output area
CALL ITOA ; .. fill in page number
MOV DX, OFFSET TITLE_ ; dx -> title
MOV CX, TITLE_LEN ; cx = length of title
CALL WRITE ; print title line
POP DI ; restore registers
POP BX
POP AX
RET ; return to caller
MKTITLE ENDP
; ---------------------------------------------------------------------------
; PAGEBREAK - Handle page overflow condition
; ---------------------------------------------------------------------------
PAGEBREAK PROC
PUSH BX ; save registers
PUSH CX
PUSH DX
TEST PAGENO, 1 ; q. finishing up with left page?
JZ PAGEBRK20 ; a. no .. do other page
MOV DX, OFFSET STRING3 ; dx -> get to right page string
MOV CX, STRING3_LEN ; cx = length
CALL WRITE ; write out 1st part of string
MOV BX, 66 ; bx = loop count
MOV CX, 3 ; cx = nbr of chars to print
MOV DX, OFFSET STRING4 ; dx -> vertical bar string
PAGEBRK10: CALL WRITE ; write on line of vertical bars
DEC BX ; q. done yet?
JNZ PAGEBRK10 ; a. no .. keep looping
MOV DX, OFFSET STRING5 ; dx -> string to finish up
MOV CX, STRING5_LEN ; cx = length
JMP PAGEBRK30 ; ..and continue w/common code
PAGEBRK20: MOV DX, OFFSET STRING6 ; dx -> get to left page string
MOV CX, STRING6_LEN ; cx = length
PAGEBRK30: CALL WRITE ; print the init line
MOV LINECNT, 1 ; reset line counter
MOV NEWPAGE, 0 ; clear new page request flag
INC PAGENO ; ..and bump page number
CALL MKTITLE ; print title line
POP DX ; restore registers
POP CX ;
POP BX ;
RET ; ..and return to caller
PAGEBREAK ENDP
; ---------------------------------------------------------------------------
; BUMPLINE - Increment line counter and test for overflow
; ---------------------------------------------------------------------------
BUMPLINE PROC
INC LINECNT ; increment line counter
CMP LINECNT, 66 ; q. reached max lines/page?
JLE BUMPLINE90 ; a. no .. continue
MOV NEWPAGE, 1 ; else .. show we'll need a new one
BUMPLINE90: RET ; ..then return to caller
BUMPLINE ENDP
; ---------------------------------------------------------------------------
; PROLOGUE - Put out laserjet initialization string
; ---------------------------------------------------------------------------
PROLOGUE PROC
PUSH CX ; save registers
PUSH DX
MOV DX, OFFSET STRING1 ; dx -> initialization string
MOV CX, STRING1_LEN ; cx = length
CALL WRITE ; print the init line
MOV PAGENO, 1 ; setup page number
MOV CURCOL, 1 ; ..and current column number
MOV LINECNT, 1 ; ..and line counter
MOV HPSTATE, 1 ; ..show in left page
MOV USEDLEN, 0 ; ..clear column position
CALL MKTITLE ; print title line
POP DX ; restore registers
POP CX ;
RET ; ..and return to caller
PROLOGUE ENDP
; ---------------------------------------------------------------------------
; EPILOGUE - Put out laserjet finish up string
; ---------------------------------------------------------------------------
EPILOGUE PROC
PUSH CX ; save registers
PUSH DX
MOV DX, OFFSET STRING2 ; dx -> termination string
MOV CX, STRING2_LEN ; cx = length
CALL WRITE ; print the init line
MOV HPSTATE, 0 ; show back to initialization state
POP DX ; restore registers
POP CX ;
RET ; ..and return to caller
EPILOGUE ENDP
; ---------------------------------------------------------------------------
; WRITE - Send a string to the printer
; Entry:
; dx -> string to write
; cx = nbr of characters
; ---------------------------------------------------------------------------
WRITE PROC
PUSH AX ; save registers
PUSH BX
MOV AH, 40H ; ah = write to file/device function
MOV BX, PHANDLE ; bx = printer handle
INT 21H ; issue dos call
POP BX ; restore registers
POP AX ;
RET ; ..and return to caller
WRITE ENDP
; ---------------------------------------------------------------------------
; UPCASE - Convert command line arguments to uppercase
; ---------------------------------------------------------------------------
UPCASE PROC
PUSH SI ; save caller regs
PUSH DI
MOV SI, 81H ; si -> start of parm area
MOV DI, SI ; .. same for di
CLD ; .. assure ascending
UPCASE10: LODSB ; al = char
CMP AL, 0DH ; q. end of line?
JE UPCASE90 ; a. yes .. end of line!
CMP AL, 'a' ; q. is it below 'a'?
JB UPCASE20 ; a. yes .. continue
CMP AL, 'z' ; q. is it above 'z'?
JA UPCASE20 ; a. yes .. continue
SUB AL, 20H ; set to upper case
UPCASE20: STOSB ; save the byte
JMP UPCASE10 ; .. and continue
UPCASE90: POP DI ; restore caller regs
POP SI
RET ; .. and return to caller
UPCASE ENDP
; ---------------------------------------------------------------------------
; ATOI - Translate an ascii value to binary
; Entry:
; si -> ascii value
; Exit:
; al = binary value
; ---------------------------------------------------------------------------
ATOI PROC
XOR AX, AX ; ax = accumulator = 0
ATOI10: CMP BYTE PTR [SI], '0' ; q. below ascii 0?
JB ATOI90 ; a. yes.. exit
CMP BYTE PTR [SI], '9' ; q. above ascii 9?
JA ATOI90 ; a. yes.. exit
XOR AH, AH ; reset ah
MOV BL, 10 ; bl = multiply value
MUL BL ; .. multiply by 10
MOV BL, [SI] ; bl = value
AND BL, 0FH ; .. upper bits off
ADD AL, BL ; .. add to bl
INC SI ; si -> next char
JMP ATOI10 ; .. tranlate it
ATOI90: RET ; .. return to caller
ATOI ENDP
; ---------------------------------------------------------------------------
; ITOA - Integer to ASCII characters
; Entry:
; ax = value to convert
; bl = fill character
; cx = nbr of characters
; di -> start of alpha area
; ---------------------------------------------------------------------------
ITOA PROC
PUSH AX ; save registers
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSHF
STD ; ..and set direction flag
ADD DI, CX ; di -> 1st char past work area
DEC DI ; di -> last char in work area
PUSH BX ; save fill character
MOV BX, 10 ; bx = divisor
ITOA10: OR AX, AX ; q. any value to convert?
JZ ITOA20 ; a. no .. exit loop
XOR DX, DX ; dx:ax = value to divide
IDIV BX ; ax = dividend, dx = remainder
OR DL, 30H ; dl = ASCII number
MOV [DI], DL ; store character in buffer
DEC DI ; di -> next output char location
DEC CX ; q. any more room in buffer?
JNZ ITOA10 ; a. yes .. continue loop
POP BX ; restore register
JMP ITOA90 ; ..and exit through common code
ITOA20: POP AX ; al = fill character
ITOA30: STOSB ; store fill character
DEC CX ; q. any more room in buffer?
JNZ ITOA30 ; a. yes .. continue loop
ITOA90: POPF ; restore flags
POP DI ; ..and registers
POP DX ;
POP CX ;
POP BX ;
POP AX ;
RET ; ..and return
ITOA ENDP
; ---------------------------------------------------------------------------
; Uninitialized data areas
; ---------------------------------------------------------------------------
UDATA EQU $ ; start of unitialized data
PAGENO EQU WORD PTR UDATA ; current page number
CURCOL EQU WORD PTR PAGENO+2 ; current column
LINECNT EQU WORD PTR CURCOL+2 ; line count
EDRV EQU BYTE PTR LINECNT+2 ; current disk
EDIR EQU BYTE PTR EDRV+1 ; current directory
FILENAME EQU BYTE PTR EDIR+65 ; filename specifed as ARG1
LASTBUFF EQU BYTE PTR FILENAME+13 ; last buffer indicator
FHANDLE EQU WORD PTR LASTBUFF+1 ; input file handle
BUFFER EQU BYTE PTR FHANDLE+2 ; file buffer
BUFLEN EQU 2048 ; length of buffer
USEDLEN EQU BYTE PTR BUFFER+BUFLEN ; used length in a logical line
OBUFF EQU BYTE PTR USEDLEN+1 ; output buffer - must be last!
CSEG ENDS ; end of code segment
END START